﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Windows.Media;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using Styx;
using Styx.Helpers;
using Styx.Common;
using Styx.CommonBot.POI;
using Styx.CommonBot;
using Styx.CommonBot.Routines;
using Styx.Pathing;
using Styx.WoWInternals;
using Styx.WoWInternals.WoWObjects;
using Styx.TreeSharp;
using Action = Styx.TreeSharp.Action;

namespace ForstDoeninge
{
    public partial class Classname : CombatRoutine
    {
        Stopwatch wachtTimer = new Stopwatch();
        #region Buffs
        public bool Buffs()
        {
            if (!Me.Mounted && !Me.IsDead && !Me.IsGhost)
            {
                if (!Me.Combat
                    && !HebEten
                    && LastSpell != "Conjure Refreshment")
                {
                    SpellCast("Conjure Refreshment", 2);
                }
                if (!HaveManaGem
                    && LastSpell != "Conjure Mana Gem")
                {
                    SpellCast("Conjure Mana Gem", 2);
                }
                if (gotTarget
                    && Me.Combat
                    && !spellOnCooldown("Arcane Torrent")
                    && Me.ManaPercent <= CRSettings.myPrefs.ArcaneTorrent)
                {
                    SpellCast("Arcane Torrent", 2);
                }
                if (gotTarget
                    && Me.Combat
                    && !spellOnCooldown("Gift of the Naruu")
                    && Me.HealthPercent <= CRSettings.myPrefs.naruupercent)
                {
                    BuffCast("Gift of the Naruu", 2);
                }
                if (Me.Pet == null
                    && !Me.Mounted
                    && !Me.IsFlying
                    && !Me.IsOnTransport
                    && !Me.OnTaxi
                    && !spellOnCooldown("Summon Water Elemental")
                    && LastSpell != "Summon Water Elemental")
                {
                    SpellCast("Summon Water Elemental", 2);
                }
                if (Me.Pet != null
                    && Me.Pet.IsDead
                    && !spellOnCooldown("Summon Water Elemental"))
                {
                    SpellCast("Summon Water Elemental", 2);
                }
                if (gotTarget
                    && Me.Combat
                    && !buffExists("Ice Barrier", Me)
                    && !spellOnCooldown("IceBarrier")
                    && Me.HealthPercent <= CRSettings.myPrefs.IceBarrier)
                {
                    BuffCast("Ice Barrier", 2);
                }
                if (CRSettings.myPrefs.Armor == 1
                    && !buffExists("Frost Armor", Me)
                    && LastSpell != "Frost Armor")
                {
                    BuffCast("Frost Armor", 2);
                }
                if (CRSettings.myPrefs.Armor == 2
                    && !buffExists("Mage Armor", Me)
                    && LastSpell != "Mage Armor")
                {
                    BuffCast("Mage Armor", 2);
                }
                if (CRSettings.myPrefs.Armor == 3
                    && !buffExists("Molten Armor", Me)
                    && LastSpell != "Molten Armor")
                {
                    BuffCast("Molten Armor", 2);
                }
                if (!buffExists("Arcane Brilliance", Me)
                    && !buffExists("Burning Wrath", Me)
                    && !buffExists("Still Water", Me)
                    && LastSpell != "Arcane Brilliance")
                {
                    BuffCast("Arcane Brilliance", 2);
                }
                if (gotTarget
                    && Me.Combat
                    && !buffExists("Incanter's Ward", Me)
                    && !spellOnCooldown("Incanter's Ward"))
                {
                    BuffCast("Incanter's Ward", 2);
                }
                if (gotTarget
                    && Me.Combat
                    && Me.HealthPercent <= CRSettings.myPrefs.healthstonepercent)
                {
                    useHealthStone();
                }
                if (CRSettings.myPrefs.alchemyflask
                    && !buffExists("Enhanced Intellect", Me)
                    && !buffExists("Flask of the Warm Sun", Me))
                {
                    useAlchemistFlask();
                }
                if (CRSettings.myPrefs.intflask
                    && Me.GroupInfo.IsInRaid
                    && !buffExists("Flask of the Warm Sun", Me))
                {
                    useFlask();
                }
            }
            return false;
        }
        #endregion Buffs

        #region petcasting
        public bool CanCastPetAction(string action)
        {
            WoWPetSpell petAction = StyxWoW.Me.PetSpells.FirstOrDefault(p => p.ToString() == action);
            if (petAction == null || petAction.Spell == null)
            {
                return false;
            }
            return !petAction.Spell.Cooldown;
        }
        public void CastPetAction(string action)
        {
            WoWPetSpell spell = StyxWoW.Me.PetSpells.FirstOrDefault(p => p.ToString() == action);
            if (spell == null)
                return;

            Lua.DoString("CastPetAction({0})", spell.ActionBarIndex + 1);
            SpellManager.ClickRemoteLocation(Me.CurrentTarget.Location);
            LogMsg("Pet is casting Freeze", 2);
        }
        #endregion petcasting

        #region spellcasting
        public void SpellCast(string spell, int kleurtje)
        {
            if (SpellManager.HasSpell(spell) && SpellManager.CanCast(spell))
            {
                SpellManager.Cast(spell);
                LogMsg(spell, kleurtje);
                LastSpell = spell;
            }
        }
        public void BuffCast(string spell, int kleurtje)
        {
            if (SpellManager.HasSpell(spell) && SpellManager.CanCast(spell))
            {
                SpellManager.Cast(spell, Me);
                LogMsg(spell, kleurtje);
                LastSpell = spell;
            }
        }
        public void DropCast(string spell, int kleurtje)
        {
            if (SpellManager.HasSpell(spell) && SpellManager.CanCast(spell))
            {
                SpellManager.Cast(spell);
                SpellManager.ClickRemoteLocation(Me.CurrentTarget.Location);
                LogMsg(spell, kleurtje);
                LastSpell = spell;
            }

        }
        #endregion spellcasting

        #region spell checks

        public string HavePotionBuff { get; set; }
        public string HaveFlaskBuff { get; set; }
        public string HaveHealPotions { get; set; }
        public string HaveLifeSpirit { get; set; }
        public string HaveHealthStone { get; set; }
        public string LastSpell { get; set; }

        #endregion spell checks

        #region IsInRange
        public bool IsInRange(float range, WoWUnit target)
        {
            if (Me.CurrentTarget.Distance <= range)
            {
                return true;
            }
            return false;
        }
        public bool IsInPetRange(float petrange, WoWUnit target)
        {
            WoWPoint petloc = Me.Pet.Location;

            if (petloc.Distance(target.Location) <= petrange)
            {
                return true;
            }

            return false;
        }
        #endregion IsInRange

        #region hastebuffs
        private bool HaveHasteBuff
        {
            get
            {
                if (buffExists("Tiger's Fury", Me)
                    && buffExists("Heroism", Me)
                    && buffExists("Bloodlust", Me)
                    && buffExists("Ancient Hysteria", Me))
                {
                    return true;
                }
                return false;
            }
        }
        #endregion hastebuffs

        #region statsbuffs
        public bool HaveStatsBuffs
        {
            get
            {
                if (buffExists("Mark of the Wild", Me)
                    || buffExists("Blessing of Kings", Me)
                    || buffExists("Legacy of the Emperor", Me)
                    || buffExists("Embrace of the Shale Spider", Me))
                {
                    return true;
                }
                return false;
            }
        }
        #endregion statsbuffs

        #region GetAsyncKeyState

        [DllImport("user32.dll")]
        private static extern short GetAsyncKeyState(Keys vKey);

        #endregion

        #region pause


        public bool Paused = false;
        public bool PauseAoe = false;

        public override void ShutDown()
        {
            Lua.Events.DetachEvent("MODIFIER_STATE_CHANGED", HandleModifierStateChanged);
        }

        private void HandleModifierStateChanged(object sender, LuaEventArgs args)
        {
            if (CRSettings.myPrefs.PauseKeys == CRSettings.Keypress.None
                && CRSettings.myPrefs.AoePauseKeys == CRSettings.Keypress.None)
            {
                return;
            }

            if (Convert.ToInt32(args.Args[1]) == 1)
            {
                if (args.Args[0].ToString() == CRSettings.myPrefs.AoePauseKeys.ToString())
                {
                    PauseAoe = !PauseAoe;
                    if (PauseAoe)
                    {
                        Logging.Write("Bear Aoe Paused, press {0} in WOW again to switch back to Cat Form",
                                     CRSettings.myPrefs.AoePauseKeys.ToString());
                        if (CRSettings.myPrefs.PrintMsg)
                            Lua.DoString(
                                "RaidNotice_AddMessage(RaidWarningFrame, \"Stopping Bear Aoe\", ChatTypeInfo[\"RAID_WARNING\"]);");
                    }
                    else
                    {
                        Logging.Write("Bear Aoe Resumed");
                        if (CRSettings.myPrefs.PrintMsg)
                            Lua.DoString(
                                "RaidNotice_AddMessage(RaidWarningFrame, \"Bear Aoe enabled again\", ChatTypeInfo[\"RAID_WARNING\"]);");
                    }
                }
            }
            if (Convert.ToInt32(args.Args[1]) == 1)
            {
                if (args.Args[0].ToString() == CRSettings.myPrefs.PauseKeys.ToString())
                {
                    Paused = !Paused;
                    if (Paused)
                    {
                        Logging.Write("CR paused, press {0} in WOW again to turn back on",
                                     CRSettings.myPrefs.PauseKeys.ToString());
                        if (CRSettings.myPrefs.PrintMsg)
                            Lua.DoString(
                                "RaidNotice_AddMessage(RaidWarningFrame, \"CR Paused\", ChatTypeInfo[\"RAID_WARNING\"]);");
                    }
                    else
                    {
                        Logging.Write("CR running again ....");
                        if (CRSettings.myPrefs.PrintMsg)
                            Lua.DoString(
                                "RaidNotice_AddMessage(RaidWarningFrame, \"CR running again ....\", ChatTypeInfo[\"RAID_WARNING\"]);");
                    }
                }
            }
        }
        #endregion pause

        #region logs
        public void LogMsg(string msg, int kleurtje)
        {
            Color kleur = Colors.Yellow;
            switch (kleurtje)
            {
                case 0:
                    kleur = Colors.Orange;
                    break;
                case 1:
                    kleur = Colors.PaleGreen;
                    break;
                case 2:
                    kleur = Colors.BlanchedAlmond;
                    break;
                case 3:
                    kleur = Colors.Yellow;
                    break;
                case 4:
                    kleur = Colors.Red;
                    break;
                case 6:
                    kleur = Colors.LightBlue;
                    break;
                case 5:
                    kleur = Colors.Crimson;
                    break;
                case 7:
                    kleur = Colors.Cyan;
                    break;
                case 8:
                    kleur = Colors.DarkSeaGreen; // TotH
                    break;
                case 9:
                    kleur = Colors.Honeydew; //Lock and load
                    break;
                case 10:
                    kleur = Colors.DeepSkyBlue; //focusdump
                    break;
            }
            Logging.Write(kleur, msg);
        }
        #endregion logs

        #region AddCounting
        private int addCount
        {
            get
            {
                int count = 0;
                foreach (WoWUnit u in ObjectManager.GetObjectsOfType<WoWUnit>(true, true))
                {
                    if (gotTarget
                        && u.CanSelect
                        && !u.IsPlayer
                        && u.IsAlive
                        && u.Guid != Me.Guid
                        && !u.IsFriendly
                        && u.IsHostile
                        && u.Attackable
                        && !u.IsTotem
                        && !u.IsCritter
                        && !u.IsNonCombatPet
                        && (u.Location.Distance(Me.CurrentTarget.Location) <= 10 || u.Location.Distance2D(Me.CurrentTarget.Location) <= 10))
                    {
                        count++;
                    }
                }
                return count;
            }
        }
        IEnumerable<WoWUnit> UnfriendlyUnits
        {
            get
            {
                return ObjectManager.GetObjectsOfType<WoWUnit>(true, false).Where(u => !u.IsDead
                    && u.CanSelect
                    && u.Attackable
                    && !u.IsFriendly
                    && u.Location.Distance2D(Me.CurrentTarget.Location) <= 3);
            }
        }
        #endregion AddCounting

        #region Kind of target
        public bool IsWoWBoss(WoWUnit mytarget)
        {

            if (gotTarget
                && Me.CurrentTarget.CreatureRank == WoWUnitClassificationType.WorldBoss)
            {
                return true;
            }
            else if (gotTarget
                && target.IsBoss(mytarget))
            {
                return true;
            }
            else if (gotTarget
                && Me.CurrentTarget.MaxHealth >= (65 * 1000000))
            {
                return true;
            }
            else if (gotTarget
                && Me.CurrentTarget.CreatureRank == WoWUnitClassificationType.RareElite
                && Me.CurrentTarget.MaxHealth >= (Me.MaxHealth * CRSettings.myPrefs.ElitesHealth)
                && !Me.IsInInstance
                && !Me.GroupInfo.IsInRaid)
            {
                return true;
            }
            else if (gotTarget
                     && Me.CurrentTarget.CreatureRank == WoWUnitClassificationType.Rare
                     && Me.CurrentTarget.MaxHealth >= (Me.MaxHealth * CRSettings.myPrefs.ElitesHealth)
                     && !Me.IsInInstance
                     && !Me.GroupInfo.IsInRaid)
            {
                return true;
            }
            else if (gotTarget
                && Me.CurrentTarget.CreatureRank == WoWUnitClassificationType.Elite
                && Me.CurrentTarget.MaxHealth >= (Me.MaxHealth * CRSettings.myPrefs.ElitesHealth)
                && !Me.IsInInstance
                && !Me.GroupInfo.IsInRaid)
            {
                return true;
            }
            else if (gotTarget
                && Me.CurrentTarget.Name.Contains("Training Dummy")
                && !Me.IsInInstance)
            {
                return true;
            }
            else if (gotTarget
                && Me.CurrentTarget.IsPlayer
                && !Me.CurrentTarget.IsFriendly)
            {
                return true;
            }
            return false;
        }

        #endregion Kind of Target

        #region trinkets + flasks
        public void useAlchemistFlask()
        {
            WoWItem alchflask = Me.BagItems.FirstOrDefault(h => h.Entry == 75525);

            if (alchflask != null && LastSpell != "AlchFlask")
            {
                alchflask.Use();
                Logging.Write(Colors.LightBlue, "Using Alchemist's Flask");
                LastSpell = "AlchFlask";
            }

        }
        public void useJadePotion()
        {
            WoWItem potion = Me.BagItems.FirstOrDefault(h => h.Entry == 76093);

            if (potion == null)
            {
                return;
            }
            if (potion != null && potion.CooldownTimeLeft.TotalMilliseconds <= 0 && LastSpell != "jade")
            {
                potion.Use();
                Logging.Write(Colors.BlanchedAlmond, "Using " + potion.Name);
                LastSpell = "jade";
            }

        }
        public void useHealthStone()
        {
            WoWItem hstone = Me.BagItems.FirstOrDefault(h => h.Entry == 5512);
            if (hstone == null)
            {
                return;
            }
            if (hstone != null && hstone.CooldownTimeLeft.TotalMilliseconds <= 0)
            {
                hstone.Use();
                Logging.Write(Colors.BlanchedAlmond, "Using " + hstone.Name);
            }
        }
        public void useFlask()
        {
            WoWItem flask = Me.BagItems.FirstOrDefault(h => h.Entry == 76085);
            if (flask == null)
            {
                return;
            }
            if (flask != null && flask.CooldownTimeLeft.TotalMilliseconds <= 0)
            {
                flask.Use();
                Logging.Write(Colors.BlanchedAlmond, "Using " + flask.Name);
            }
        }
        public void useTrinket1()
        {
            var firstTrinket = StyxWoW.Me.Inventory.Equipped.Trinket1;
            if (firstTrinket != null && CanUseEquippedItem(firstTrinket) && LastSpell != "trinket1")
            {
                firstTrinket.Use();
                LogMsg("Using 1st trinket", 2);
            }
        }
        public void useTrinket2()
        {
            var secondTrinket = StyxWoW.Me.Inventory.Equipped.Trinket2;

            if (secondTrinket != null && CanUseEquippedItem(secondTrinket) && LastSpell != "trinket2")
            {
                secondTrinket.Use();
                LogMsg("Using 2nd trinket", 2);
            }

        }
        public void useEngiGloves()
        {
            var engiGloves = StyxWoW.Me.Inventory.Equipped.Hands;


            if (engiGloves != null && CanUseEquippedItem(engiGloves) && LastSpell != "gloves")
            {
                engiGloves.Use();
                LogMsg("Using Engineer Gloves", 2);
                LastSpell = "gloves";
            }
        }
        private static bool CanUseEquippedItem(WoWItem item)
        {
            // Check for engineering tinkers!
            string itemSpell = Lua.GetReturnVal<string>("return GetItemSpell(" + item.Entry + ")", 0);
            if (string.IsNullOrEmpty(itemSpell))
                return false;


            return item.Usable && item.Cooldown <= 0;
        }
        #endregion trinkets + flasks

        #region Buff Checks

        public bool buffExists(int Buff, WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                var Results = onTarget.GetAuraById(Buff);
                if (Results != null)
                    return true;
            }
            return false;
        }

        public double buffTimeLeft(int Buff, WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                var Results = onTarget.GetAuraById(Buff);
                if (Results != null)
                {
                    if (Results.TimeLeft.TotalMilliseconds > 0)
                        return Results.TimeLeft.TotalMilliseconds;
                }
            }
            return 0;
        }

        public bool buffExists(string Buff, WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                var Results = onTarget.GetAuraByName(Buff);
                if (Results != null)
                    return true;
            }
            return false;
        }

        public double buffTimeLeft(string Buff, WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                var Results = onTarget.GetAuraByName(Buff);
                if (Results != null)
                {
                    if (Results.TimeLeft.TotalMilliseconds > 0)
                        return Results.TimeLeft.TotalMilliseconds;
                }
            }
            return 0;
        }



        public uint buffStackCount(int Buff, WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                var Results = onTarget.GetAuraById(Buff);
                if (Results != null)
                    return Results.StackCount;
            }
            return 0;
        }
        public uint buffStackCount(string Buff, WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                var Results = onTarget.GetAuraByName(Buff);
                if (Results != null)
                    return Results.StackCount;
            }
            return 0;
        }
        #endregion

        #region Cache Checks
        public IEnumerable<WoWAura> cachedAuras = new List<WoWAura>();
        public IEnumerable<WoWAura> cachedTargetAuras = new List<WoWAura>();
        public void getCachedAuras()
        {
            if (Me.CurrentTarget != null)
                cachedTargetAuras = Me.CurrentTarget.GetAllAuras();
            cachedAuras = Me.GetAllAuras();
        }
        #endregion

        #region Cooldown Checks
        private Dictionary<WoWSpell, long> Cooldowns = new Dictionary<WoWSpell, long>();
        public TimeSpan cooldownLeft(int Spell)
        {
            SpellFindResults Results;
            if (SpellManager.FindSpell(Spell, out Results))
            {
                WoWSpell Result = Results.Override ?? Results.Original;
                if (Cooldowns.TryGetValue(Result, out lastUsed))
                {
                    if (DateTime.Now.Ticks < lastUsed)
                        return Result.CooldownTimeLeft;
                    return TimeSpan.MaxValue;
                }
            }
            return TimeSpan.MaxValue;
        }
        public TimeSpan cooldownLeft(string Spell)
        {
            SpellFindResults Results;
            if (SpellManager.FindSpell(Spell, out Results))
            {
                WoWSpell Result = Results.Override ?? Results.Original;
                if (Cooldowns.TryGetValue(Result, out lastUsed))
                {
                    if (DateTime.Now.Ticks < lastUsed)
                        return Result.CooldownTimeLeft;
                    return TimeSpan.MaxValue;
                }
            }
            return TimeSpan.MaxValue;
        }
        long lastUsed;
        public int lastCast;
        public bool onCooldown(int Spell)
        {
            SpellFindResults Results;
            if (SpellManager.FindSpell(Spell, out Results))
            {
                WoWSpell Result = Results.Override ?? Results.Original;
                if (Cooldowns.TryGetValue(Result, out lastUsed))
                {
                    if (DateTime.Now.Ticks < lastUsed)
                        return Result.Cooldown;
                    return false;
                }
            }
            return false;
        }
        public bool onCooldown(string Spell)
        {
            SpellFindResults Results;
            if (SpellManager.FindSpell(Spell, out Results))
            {
                WoWSpell Result = Results.Override ?? Results.Original;
                if (Cooldowns.TryGetValue(Result, out lastUsed))
                {
                    if (DateTime.Now.Ticks < lastUsed)
                        return Result.Cooldown;
                    return false;
                }
            }
            return false;
        }
        public TimeSpan spellCooldownLeft(int Spell, bool useTracker = false)
        {
            if (useTracker)
                return cooldownLeft(Spell);
            SpellFindResults results;
            if (SpellManager.FindSpell(Spell, out results))
            {
                if (results.Override != null)
                    return results.Override.CooldownTimeLeft;
                return results.Override.CooldownTimeLeft;
            }
            return TimeSpan.MaxValue;
        }
        public TimeSpan spellCooldownLeft(string Spell, bool useTracker = false)
        {
            if (useTracker)
                return cooldownLeft(Spell);
            SpellFindResults results;
            if (SpellManager.FindSpell(Spell, out results))
            {
                if (results.Override != null)
                    return results.Override.CooldownTimeLeft;
                return results.Override.CooldownTimeLeft;
            }
            return TimeSpan.MaxValue;
        }
        public bool spellOnCooldown(int Spell, bool useTracker = false)
        {
            if (useTracker)
                return !onCooldown(Spell);
            SpellFindResults results;
            if (SpellManager.FindSpell(Spell, out results))
                return results.Override != null ? results.Override.Cooldown : results.Original.Cooldown;
            return false;
        }
        public bool spellOnCooldown(string Spell, bool useTracker = false)
        {
            if (useTracker)
                return !onCooldown(Spell);
            SpellFindResults results;
            if (SpellManager.FindSpell(Spell, out results))
                return results.Override != null ? results.Override.Cooldown : results.Original.Cooldown;
            return false;
        }
        #endregion

        #region Debuff Checks

        public bool debuffExists(int Debuff, WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                WoWAura aura = onTarget.GetAllAuras().FirstOrDefault(a => a.SpellId == Debuff && a.CreatorGuid == Me.Guid);
                if (aura != null)
                {
                    return true;
                }
            }
            return false;
        }

        public double debuffTimeLeft(int Debuff, WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                WoWAura aura = onTarget.GetAllAuras().FirstOrDefault(a =>
                    a.SpellId == Debuff
                    && a.CreatorGuid == Me.Guid);

                if (aura == null)
                {
                    return 0;
                }
                return aura.TimeLeft.TotalMilliseconds;
            }
            return 0;
        }

        public uint debuffStackCount(int Debuff, WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                WoWAura aura = onTarget.GetAllAuras().FirstOrDefault(a =>
                    a.SpellId == Debuff
                    && a.CreatorGuid == Me.Guid);

                if (aura == null)
                {
                    return 0;
                }
                return aura.StackCount;
            }
            return 0;
        }
        public bool debuffExists(string Debuff, WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                WoWAura aura = onTarget.GetAllAuras().FirstOrDefault(a => a.Name == Debuff && a.CreatorGuid == Me.Guid);
                if (aura != null)
                {
                    return true;
                }
            }
            return false;
        }

        public double debuffTimeLeft(string Debuff, WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                WoWAura aura = onTarget.GetAllAuras().FirstOrDefault(a =>
                    a.Name == Debuff
                    && a.CreatorGuid == Me.Guid);

                if (aura == null)
                {
                    return 0;
                }
                return aura.TimeLeft.TotalMilliseconds;
            }
            return 0;
        }

        public uint debuffStackCount(string Debuff, WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                WoWAura aura = onTarget.GetAllAuras().FirstOrDefault(a =>
                    a.Name == Debuff
                    && a.CreatorGuid == Me.Guid);

                if (aura == null)
                {
                    return 0;
                }
                return aura.StackCount;
            }
            return 0;
        }
        #endregion

        #region Focus checks
        public double Focus
        {
            get
            {
                try
                {
                    using (StyxWoW.Memory.AcquireFrame())
                    {
                        return Styx.WoWInternals.Lua.GetReturnVal<int>("return UnitPower(\"player\");", 0);
                    }
                }
                catch { return 0; }
            }
        }
        #endregion

        #region Target Checks

        internal IEnumerable<WoWUnit> attackableTargets
        {
            get { return ObjectManager.GetObjectsOfType<WoWUnit>(true, false).Where(U => U.Attackable && U.CanSelect && !U.IsFriendly && !U.IsDead && !U.IsNonCombatPet && !U.IsCritter); }
        }
        public bool gotTarget { get { return Me.GotTarget && Me.CurrentTarget != null && Me.CurrentTarget.Attackable && (!Me.CurrentTarget.IsDead && !Me.CurrentTarget.IsFriendly || isTargetDummy); } }

        public bool isTargetDummy { get { return Me.CurrentTarget.Name == "Training Dummy" || Me.CurrentTarget.Name == "Raider's Training Dummy"; } }

        internal IEnumerable<WoWUnit> nearbyTargets(WoWPoint fromLocation, double Radius)
        {
            var Hostile = attackableTargets;
            var maxDistance = Radius * Radius;
            return Hostile.Where(x => x.Location.DistanceSqr(fromLocation) < maxDistance);
        }
        public double targetDistance(WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                var Results = onTarget.DistanceSqr;
                if (Results != null)
                    return onTarget.DistanceSqr;
            }
            return 0;
        }
        public double targetHP(WoWUnit onTarget)
        {
            if (onTarget != null)
            {
                var Results = onTarget.HealthPercent;
                if (Results != null)
                    return onTarget.HealthPercent;
            }
            return 0;
        }
        #endregion

        #region Timer Checks
        private int conv_Date2Timestam(DateTime _time)
        {
            var date1 = new DateTime(1970, 1, 1);
            DateTime date2 = _time;
            var ts = new TimeSpan(date2.Ticks - date1.Ticks);
            return (Convert.ToInt32(ts.TotalSeconds));
        }
        private uint current_life;
        private int current_time;
        private ulong guid;
        private uint first_life;
        private uint first_life_max;
        private int first_time;
        public long targetExistence(WoWUnit onTarget)
        {
            if (onTarget == null) return 0;
            if (isTargetDummy) return 9999;
            if (onTarget.CurrentHealth == 0 || onTarget.IsDead || !onTarget.IsValid || !onTarget.IsAlive)
                return 0;
            if (guid != onTarget.Guid)
            {
                guid = onTarget.Guid;
                first_life = onTarget.CurrentHealth;
                first_life_max = onTarget.MaxHealth;
                first_time = conv_Date2Timestam(DateTime.Now);
            }
            current_life = onTarget.CurrentHealth;
            current_time = conv_Date2Timestam(DateTime.Now);
            var time_diff = current_time - first_time;
            var hp_diff = first_life - current_life;
            if (hp_diff > 0)
            {
                var full_time = time_diff * first_life_max / hp_diff;
                var past_first_time = (first_life_max - first_life) * time_diff / hp_diff;
                var calc_time = first_time - past_first_time + full_time - current_time;
                if (calc_time < 1) calc_time = 99;
                var time_to_die = calc_time;
                var fight_length = full_time;
                return time_to_die;
            }
            if (hp_diff < 0)
            {
                guid = onTarget.Guid;
                first_life = onTarget.CurrentHealth;
                first_life_max = onTarget.MaxHealth;
                first_time = conv_Date2Timestam(DateTime.Now);
                return -1;
            }
            if (current_life == first_life_max)
                return 9999;
            return -1;
        }
        #endregion

        #region get target
        private bool FindNewTarget = true;
        private void FindTarget()
        {
            WoWUnit newTarget = (from o in ObjectManager.ObjectList
                                 where o is WoWUnit
                                 let unit = o.ToUnit()
                                 where
                                     unit.Distance < 40
                                     && !unit.TaggedByOther
                                     && unit.Combat
                                     && unit.Attackable
                                     && unit.IsAlive
                                     && !unit.IsFriendly
                                     && !unit.IsPet
                                     && !Blacklist.Contains(unit.Guid, BlacklistFlags.All)
                                 orderby unit.Distance ascending
                                 select unit
                                 ).FirstOrDefault();

            if (newTarget.Name.Length < 2)
            {
                LogMsg("...no suitable target found .. damn, will this cause a loop?", 0);
                return;
            }
            else
            {
                newTarget.Target();
                LogMsg("...found " + newTarget.Name, 0);
                return;
            }
        }
        #endregion get target

        #region movement etc .....
        void MoveInLignOfSight()
        {
            while (!Me.CurrentTarget.InLineOfSight)
            {
                Navigator.MoveTo(StyxWoW.Me.CurrentTarget.Location);
            }
            Navigator.PlayerMover.MoveStop();
            return;

        }
        public void MoveInRange()
        {
            while (StyxWoW.Me.Location.Distance(StyxWoW.Me.CurrentTarget.Location) > CRSettings.myPrefs.range)
            {
                Navigator.MoveTo(StyxWoW.Me.CurrentTarget.Location);
            }
            Navigator.PlayerMover.MoveStop();
            return;
        }

        public void Facing()
        {
            if (gotTarget && !Me.IsSafelyFacing(Me.CurrentTarget))
            {
                Me.CurrentTarget.Face();
            }
        }
        #endregion movement etc ....

        #region conjure items
        public static bool HebEten { get { return StyxWoW.Me.BagItems.Any(item => MageVoedsel.Contains(item.Entry)); } }
        private static bool HaveManaGem { get { return StyxWoW.Me.BagItems.Any(i => i.Entry == 36799 || i.Entry == 81901); } }

        private static readonly uint[] MageVoedsel = new uint[]
         {
                                                             65500,
                                                             65515,
                                                             65516,
                                                             65517,
                                                             43518,
                                                             43523,
                                                             65499,
                                                             80610, 
                                                             80618  
                                                         };
        #endregion conjure items


        //einde helpers
    }
}
